﻿using System;
using System.Data;
using System.Collections;

using iTunesLib;

using Blackhole.Debug;

namespace iTunesPwned.Core.iTunes
{
    public class iTunesPlayer
    {
        public enum IAttribute { Artwork, Album, Artist, Genre, TrackNumber, Year, Location, Name };

        private iTunesApp m_itunes;
        private DataTable m_ituensTable;
        private IITLibraryPlaylist m_library;

        public iTunesPlayer(DataTable itunesTable)
        {
            try
            {
                this.m_ituensTable = itunesTable;

                this.m_itunes = new iTunesAppClass();

                this.m_library = this.m_itunes.LibraryPlaylist;
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public bool NeedsUpdate()
        {
            return (this.m_library.Tracks.Count != this.m_ituensTable.Rows.Count) ? true : false;
        }

        public void UpdateRow(DataRow row, IAttribute attribute, object value)
        {
            IITTrack track = this.m_library.Tracks.get_ItemByPersistentID((int)row["persishigh"], (int)row["persislow"]);

            switch (attribute)
            {
                case IAttribute.TrackNumber: track.TrackNumber = int.Parse(value as string); break;
            }
        }

        public void Update()
        {
            try
            {
                if (this.m_library.Tracks.Count > this.m_ituensTable.Rows.Count)
                {
                    DataRow newRow;
                    object tempObj;
                    IITFileOrCDTrack file;

                    foreach (IITTrack track in this.m_library.Tracks)
                    {
                        tempObj = (object)track;
                        file = (IITFileOrCDTrack)track;

                        newRow = this.m_ituensTable.NewRow();

                        newRow["kind"] = track.KindAsString;
                        newRow["album"] = track.Album;
                        newRow["artist"] = track.Artist;
                        newRow["bitrate"] = track.BitRate;
                        newRow["duration"] = track.Duration;
                        newRow["genre"] = track.Genre;
                        newRow["size"] = track.Size;
                        newRow["tracknumber"] = track.TrackNumber;
                        newRow["year"] = track.Year;
                        newRow["location"] = file.Location;
                        newRow["persishigh"] = this.m_itunes.get_ITObjectPersistentIDHigh(ref tempObj);
                        newRow["persislow"] = this.m_itunes.get_ITObjectPersistentIDLow(ref tempObj);
                        newRow["guid"] = Guid.NewGuid();
                        newRow["name"] = track.Name;

                        try
                        {
                            this.m_ituensTable.Rows.Add(newRow);

                            Garbage.Log(this, new LoggerArguements(LoggerArguements.LoggerLevels.All, "Adding row: artist-{0} album-{1} name-{2}", newRow["artist"], newRow["album"], newRow["name"]));
                        }
                        catch (ConstraintException) { }
                    }
                }
                else
                {
                    int high, low;
                    IITTrack track;

                    foreach (DataRow row in this.m_ituensTable.Rows)
                    {
                        low = (int)row["persislow"];
                        high = (int)row["persishigh"];

                        track = this.m_library.Tracks.get_ItemByPersistentID(high, low);

                        if (track == null)
                        {
                            Garbage.Log(this, new LoggerArguements(LoggerArguements.LoggerLevels.All, "Removing row: artist-{0} album-{1} name-{2}", row["artist"], row["album"], row["name"]));

                            this.m_ituensTable.Rows.Remove(row);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void Verify()
        {
            try
            {
                IITTrack track;
                IITFileOrCDTrack file;
                ArrayList removeRows = new ArrayList();

                foreach (DataRow row in this.m_ituensTable.Rows)
                {
                    track = this.m_library.Tracks.get_ItemByPersistentID((int)row["persishigh"], (int)row["persislow"]);

                    if (track == null)
                    {
                        removeRows.Add(row);

                        continue;
                    }

                    file = (IITFileOrCDTrack)track;

                    string value = string.Empty; ;

                    foreach (DataColumn column in this.m_ituensTable.Columns)
                    {
                        switch (column.ColumnName)
                        {
                            case "kind": value = track.KindAsString; break;
                            case "album": value = track.Album; break;
                            case "artist": value = track.Artist; break;
                            case "bitrate": value = track.BitRate.ToString(); break;
                            case "duration": value = track.Duration.ToString(); break;
                            case "genre": value = track.Genre; break;
                            case "size": value = track.Size.ToString(); break;
                            case "tracknumber": value = track.TrackNumber.ToString(); break;
                            case "year": value = track.Year.ToString(); break;
                            case "location": value = file.Location; break;
                            case "name": value = track.Name; break;
                            default: continue;
                        }

                        if (row[column].ToString() != value)
                        {
                            Garbage.Log(this, new LoggerArguements(LoggerArguements.LoggerLevels.All, "Updating column {0}: {1} -> {2}", column.ColumnName, row[column], value));

                            row[column] = value;
                        }
                    }
                }

                foreach (DataRow row in removeRows)
                {
                    Garbage.Log(this, new LoggerArguements(LoggerArguements.LoggerLevels.All, "Removing row: artist-{0} album-{1} name-{2}", row["artist"], row["album"], row["name"]));

                    this.m_ituensTable.Rows.Remove(row);
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public DataTable Find(IAttribute attribute, string value)
        {
            this.m_ituensTable.DefaultView.RowFilter = string.Format("{0}='{1}'", attribute, value);

            return this.m_ituensTable.DefaultView.ToTable();
        }

        public DataTable FindMissing(IAttribute attribute)
        {
            string filter = string.Empty;

            switch (attribute)
            {
                case IAttribute.Album: filter = "Isnull(album, 'Null Column') = 'Null Column'"; break;
                case IAttribute.Artist: filter = "Isnull(artist, 'Null Column') = 'Null Column'"; break;
                case IAttribute.Genre: filter = "Isnull(genre, 'Null Column') = 'Null Column'"; break;
                case IAttribute.Location: filter = "Isnull(location, 'Null Column') = 'Null Column'"; break;
                case IAttribute.Name: filter = "Isnull(name, 'Null Column') = 'Null Column'"; break;
                case IAttribute.TrackNumber: filter = "tracknumber = '0'"; break;
                case IAttribute.Year: filter = "Isnull(year, 'Null Column') = 'Null Column'"; break;
            }

            this.m_ituensTable.DefaultView.RowFilter = filter;

            return this.m_ituensTable.DefaultView.ToTable();
        }

        public void Add(string file)
        {
            try
            {
                this.m_library.AddFile(file);
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public void Delete(DataRow row)
        {
            try
            {
                IITTrack track = this.m_library.Tracks.get_ItemByPersistentID(int.Parse(row["persishigh"] as string), int.Parse(row["persislow"] as string));

                track.Delete();

                this.m_ituensTable.Rows.Remove(row);
            }
            catch (Exception e)
            {
                throw e;
            }
        }
    }

    public interface IPlayer
    {
        iTunesPlayer Player { set; get; }
    }
}